package com.cndw.kungfu.socket;

import java.io.IOException;
import java.io.InputStream;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBufferInputStream;
import org.jboss.netty.buffer.ChannelBuffers;

import com.cndw.commons.util.BlankUtils;
import com.cndw.rpg.framework.codec.Compress;

import flex.messaging.io.ClassAliasRegistry;
import flex.messaging.io.SerializationContext;
import flex.messaging.io.amf.Amf3Input;

public class SocketClient {
	private Integer serverId;
	private String svrId;
	private InetSocketAddress address;
	private String host;
	private int port;

	private static final Map<Integer, SocketClient> allSocketClients = new ConcurrentHashMap<Integer, SocketClient>();

	/**
	 * AMF 鏄犲皠
	 */
	static {
//		ClassAliasRegistry.getRegistry().registerAlias("com.cndw.rpg.framework.ResponseMessage", "com.cndw.kungfu.socket.SocketResponse");
//		ClassAliasRegistry.getRegistry().registerAlias("com.cndw.kungfu.domain.Player", "com.cndw.kungfu.socket.vo.Player");
//		ClassAliasRegistry.getRegistry().registerAlias("com.cndw.kungfu.vo.UnionVO", "com.cndw.kungfu.socket.vo.Union");
//		ClassAliasRegistry.getRegistry().registerAlias("com.cndw.kungfu.domain.Notice", "com.cndw.kungfu.socket.vo.Notice");
//		ClassAliasRegistry.getRegistry().registerAlias("com.cndw.kungfu.domain.LogPlayer", "com.cndw.kungfu.socket.vo.PlayerLog");
//		ClassAliasRegistry.getRegistry().registerAlias("com.cndw.kungfu.vo.ModeRecordVO", "com.cndw.kungfu.socket.vo.Record");
//		ClassAliasRegistry.getRegistry().registerAlias("com.cndw.kungfu.vo.PlayerDataVO", "com.cndw.kungfu.socket.vo.PlayerData");
//		ClassAliasRegistry.getRegistry().registerAlias("com.cndw.kungfu.domain.Recharge", "com.cndw.kungfu.socket.vo.Recharge");
//		ClassAliasRegistry.getRegistry().registerAlias("com.cndw.kungfu.domain.Mail", "com.cndw.kungfu.socket.vo.Mail");
		
	}

	/**
	 * 娣诲姞瀹㈡埛绔�
	 * 
	 * @param serverId
	 * @param host
	 * @param port
	 */
	public static void addClient(Integer serverId, String svrId, String host, int port) {
		new SocketClient(serverId, svrId, host, port);
	}

	public static void removeClient(Integer serverId) {
		allSocketClients.remove(serverId);
	}

	/**
	 * 绉佹湁鏋勯�鍑芥暟
	 * 
	 * @param serverId
	 * @param host
	 * @param port
	 */
	private SocketClient(Integer serverId, String svrId, String host, int port) {
		this.serverId = serverId;
		this.host = host;
		this.port = port;
		this.svrId = svrId;
		allSocketClients.put(getServerId(), this);
	}

	/**
	 * 鍙戦�璇锋眰
	 * 
	 * @param request
	 * @return
	 */
	public static SocketResponse sendRequest(SocketRequest request) {

		SocketResponse response = new SocketResponse(); // 鍝嶅簲瀵硅薄

		if (contains(request.getServerId())) {
			SocketClient socketClient = getSocketClient(request.getServerId());
			InetSocketAddress address = socketClient.getAddress();
			Socket socket = null;
			try {
				socket = new Socket();
				socket.connect(address, 3000);
				socket.setSoTimeout(15000);
				socket.getOutputStream().write(request.serialize().array());
				socket.getOutputStream().flush();

				Amf3Input input = new Amf3Input(new SerializationContext());
				InputStream stream = socket.getInputStream();
				ChannelBuffer buffer = ChannelBuffers.dynamicBuffer();

				int bodySize = 0;// 鏈�粓
				int compressSize = 0;// 鍘嬬缉鍓�
				byte[] bytes = new byte[1024];
				while (true) {

					int length = stream.read(bytes);

					if (length != -1) {
						buffer.writeBytes(bytes, 0, length);
					}

					while (bodySize == 0 && buffer.readableBytes() >= 4) {
						bodySize = buffer.readInt();
						if (bodySize > 1024 && compressSize == 0) {
							compressSize = bodySize;
							bodySize = 0;
							continue;
						}
					}

					if (buffer.readableBytes() >= bodySize) {
						break;
					}

				}

				ChannelBuffer bodyBuffer = null;
				if (compressSize > 0) {
					byte[] cpomressBytes = Compress.decompressBytes(buffer.readBytes(bodySize).array());
					bodyBuffer = buffer.factory().getBuffer(cpomressBytes.length);
					bodyBuffer.writeBytes(cpomressBytes);
				} else {
					bodyBuffer = buffer.factory().getBuffer(bodySize);
					bodyBuffer.writeBytes(buffer, bodySize);
				}

				input.setInputStream(new ChannelBufferInputStream(bodyBuffer));
				SocketResponse message = (SocketResponse) input.readObject();

				// 涓虹┖琛ㄧず宸叉斁寮冪瓑寰呭搷搴�
				if (!BlankUtils.isBlank(message)) {
					response.setR(message.getR());
					response.setM(message.getM());
					response.setB(message.getB());
					response.setT(message.getT());
					response.setAction(message.getAction());
					response.setModule(message.getModule());
					response.setRequestId(message.getRequestId());
					response.setResponsed(true);
				}

			} catch (IOException e) {
//				LogUtils.getComm().error(
//						"Socket Err: {} {} call:{} {} {}",
//						new Object[] { e.getClass().getSimpleName(), e.getMessage(), socketClient.getSvrId(), request.getControllerName(),
//								request.getControllerMethod() });
			} catch (ClassNotFoundException e) {
				e.printStackTrace();
			} finally {
				if (!BlankUtils.isBlank(socket)) {
					try {
						socket.close();
					} catch (IOException e) {
					}
				}
			}

		}
		return response;
	}

	/**
	 * 鑾峰彇瀹㈡埛绔�
	 * 
	 * @param serverId
	 * @return
	 */
	public static SocketClient getSocketClient(Integer serverId) {
		return allSocketClients.get(serverId);
	}

	/**
	 * 鍒ゆ柇鏄惁鍖呭惈瀹㈡埛绔�
	 * 
	 * @param serverId
	 * @return
	 */
	public static boolean contains(Integer serverId) {
		return allSocketClients.containsKey(serverId);
	}

	public Integer getServerId() {
		return serverId;
	}

	public InetSocketAddress getAddress() {
		if (address == null) {
			address = new InetSocketAddress(host, port);
		}
		return address;
	}

	public String getSvrId() {
		return svrId;
	}

}
